<?php
namespace Quality\Start\Domain\Entity;

use \Quality\Start\Infra\Persistence\Entity;
use \Doctrine\Common\Collections\ArrayCollection;
use \Symfony\Component\Security\Core\User\UserInterface;
use \InvalidArgumentException;
use \Symfony\Component\Security\Core\User\AdvancedUserInterface;
use \DateTime;

/**
 * @Entity(repositoryClass="\Quality\Start\Domain\Repository\UserRepository")
 * @Table(name="user")
 **/
class User implements Entity, AdvancedUserInterface
{
    /**
     * @Id
     * @Column(type="integer")
     * @GeneratedValue(strategy="IDENTITY")
     * @var int
     */
    private $id;

    /**
     * @Column(type="string", name="username")
     * @var string
     */
    private $username;

    /**
     * @Column(type="string", length=64)
     * @var string
     */
    private $password;

    /**
     * @Column(type="datetime")
     * @var \DateTime
     */
    private $created;

    /**
     * @Column(type="datetime", name="last_access")
     * @var \DateTime
     */
    private $lastAccess;

    /**
     * @Column(type="boolean", name="is_active")
     * @var boolean
     */
    private $isActive;

    /**
     * @ManyToOne(targetEntity="People", cascade={"all"}, fetch="EAGER")
     * @var People
     **/
    private $people;

    /**
     * @ManyToMany(targetEntity="Group", inversedBy="users")
     * @JoinTable(name="users_groups")
     * @var Group[]
     **/
    private $groups;

    /**
     * @Column(type="string", length=32)
     * @var string
     */
    private $salt;

    public function __construct()
    {
        $this->isActive = true;
        $this->salt = md5(uniqid(null, true));
        $this->groups = new ArrayCollection();
    }

    /**
     * @param int $id
     */
    public function setId($id)
    {
        $this->id = $id;
    }

    /**
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @param string $username
     */
    public function setUsername($username)
    {
        $this->username = $username;
    }

    /**
     * @return string
     */
    public function getUsername()
    {
        return $this->username;
    }

    /**
     * @param string $password
     */
    public function setPassword($password)
    {
        $this->password = $password;
    }

    /**
     * @return string
     */
    public function getPassword()
    {
        return $this->password;
    }


    /**
     * @param \DateTime $created
     */
    public function setCreated(DateTime $created)
    {
        $this->created = $created;
    }

    /**
     * @return \DateTime
     */
    public function getCreated()
    {
        return $this->created;
    }

    /**
     * @param \DateTime $lastAccess
     */
    public function setLastAccess(DateTime $lastAccess)
    {
        $this->lastAccess = $lastAccess;
    }

    /**
     * @return \DateTime
     */
    public function getLastAccess()
    {
        return $this->lastAccess;
    }

    /**
     * @param $isActive
     * @throws \InvalidArgumentException
     */
    public function setIsActive($isActive)
    {
        if (!is_bool($isActive)) {
            throw new InvalidArgumentException('The active attribute must be boolean, ' . gettype($isActive) . ' given.');
        }

        $this->isActive = $isActive;
    }

    /**
     * @param People $people
     */
    public function setPeople(People $people)
    {
        $this->people = $people;
    }

    /**
     * @return People
     */
    public function getPeople()
    {
        return $this->people;
    }

    /**
     * @param \Doctrine\Common\Collections\ArrayCollection $groups
     */
    public function setGroups(ArrayCollection $groups)
    {
        $this->groups = $groups;
    }

    /**
     * @return \Doctrine\Common\Collections\ArrayCollection
     */
    public function getGroups()
    {
        return $this->groups;
    }

    /**
     * @param string $password
     * @return string
     */
    protected function generateSecret($password)
    {
        $hash = $this->salt;

        for ($i = 0; $i < 1000; ++$i) $hash = md5($hash . $password);

        return $hash . $this->salt;
    }

    /**
     * @return Boolean true if the user's account is non expired, false otherwise
     * @see AccountExpiredException
     */
    public function isAccountNonExpired()
    {
        return true;
    }

    /**
     * @return Boolean true if the user is not locked, false otherwise
     *
     * @see LockedException
     */
    public function isAccountNonLocked()
    {
        return true;
    }

    /**
     * @return Boolean true if the user's credentials are non expired, false otherwise
     *
     * @see CredentialsExpiredException
     */
    public function isCredentialsNonExpired()
    {
        return true;
    }

    /**
     * @return Boolean true if the user is enabled, false otherwise
     *
     * @see DisabledException
     */
    public function isEnabled()
    {
        return $this->isActive;
    }

    /**
     * Returns the roles granted to the user.
     *
     * @return array
     */
    public function getRoles()
    {
        return $this->groups->toArray();
    }

    /**
     * @return string
     */
    public function getSalt()
    {
        return $this->salt;
    }

    /**
     * @inheritDoc
     */
    public function eraseCredentials()
    {
        $this->password = null;
    }

    /**
     * @param UserInterface $user
     * @return bool
     */
    public function equals(UserInterface $user)
    {
        return ($this->getUsername() === $user->getUsername());
    }
}